﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using KNet.Data.Entity;
using KNet.Foundation.DRS;
using KNet.Foundation.DRS.Model;
using System.Runtime.Caching;
using CNKI.TPI.Web.Search.Model;
using KNet.Data.KBaseClient;
using System.Runtime.InteropServices;
using System.IO;
using MySql.Data.MySqlClient;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace CNKI.TPI.Web.Base
{
    public class DataContext : IDataContext
    {
        private string defualtDB = "SysDB";
        private IDictionary<string, KNet.Data.Entity.DataContext> ctxList = null;
        ChannelFactory<IRetrievalService> channel = null;
        private MemoryCache cache = MemoryCache.Default;

        public DataContext()
        {
            IList<string> dbList = new List<string>();
            dbList.Add(defualtDB);
            Init(dbList);
        }

        public DataContext(IList<string> dbList)
        {
            if (dbList.Count == 0)
            {
                dbList.Add(defualtDB);
                dbList.Add("mysql");
            }
            Init(dbList);
        }

        private KNet.Data.Entity.DataContext GetCtx(string ctxName)
        {
            KNet.Data.Entity.DataContext result = null;
            if (string.IsNullOrEmpty(ctxName))
            {
                result = ctxList[defualtDB];
            }
            else if (ctxList.ContainsKey(ctxName))
            {
                result = ctxList[ctxName];
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ctxName"></param>
        public void AddCtx(string ctxName)
        {
            ctxList.Add(ctxName, KNet.Data.Entity.DataContext.GetByConfigName(ctxName));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbList"></param>
        private void Init(IList<string> dbList)
        {
            ctxList = new Dictionary<string, KNet.Data.Entity.DataContext>();
            foreach (string item in dbList)
            {
                ctxList.Add(item, KNet.Data.Entity.DataContext.GetByConfigName(item));
            }
            if (ConfigHelper.IsDrsConfigExsit())
            {
                channel = new ChannelFactory<IRetrievalService>("drs_tcp");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public bool Insert<T>(T model, string tableName = null, string ctxName = null) where T : new()
        {

            return GetCtx(ctxName).Insert(model, tableName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public bool Update<T>(T model, string tableName = null, string ctxName = null) where T : new()
        {
            return GetCtx(ctxName).Update(model, tableName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="match"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public bool Delete<T>(Expression<Func<T, bool>> match, string tableName = null, string ctxName = null) where T : new()
        {
            return GetCtx(ctxName).Delete(match, tableName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public bool Delete<T>(T model, string tableName = null, string ctxName = null) where T : new()
        {
            return GetCtx(ctxName).Delete(model, tableName);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="match"></param>
        /// <returns></returns>
        public IList<T> Get<T>(Expression<Func<T, bool>> match, Expression<Func<T, bool>> order = null, string ctxName = null, int dataCacheTimeout = 0) where T : BaseModel, IView, new()
        {
            IList<T> result = new List<T>();
            try
            {
                //int dataCacheTimeout = ConfigHelper.GetDataCacheTimeout();
                if (0 != dataCacheTimeout)
                {
                    string key = typeof(T).Name + "|" + (match == null ? "" : match.ToString()) + "|" + (order == null ? "" : order.ToString());
                    if (cache.Contains(key))
                    {
                        result = (IList<T>)cache.Get(key);
                    }
                    else
                    {
                        result = GetCtx(ctxName).GetAll<T>(match, order);
                        cache.Add(key, result, DateTime.Now.AddSeconds(dataCacheTimeout));
                    }
                    result = result.Select(item => (T)item.Clone()).ToList();
                }
                else
                {
                    result = GetCtx(ctxName).GetAll<T>(match, order);
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="match"></param>
        /// <returns></returns>
        public IList<T> Get<T>(Expression<Func<T, bool>> match, int pageIndex, int pageSize, out int count, Expression<Func<T, bool>> order = null, string ctxName = null, int dataCacheTimeout = 0) where T : BaseModel, IView, new()
        {
            IList<T> result = new List<T>();
            int rowCount = 0;
            try
            {
                //int dataCacheTimeout = ConfigHelper.GetDataCacheTimeout();
                if (0 != dataCacheTimeout)
                {
                    string key = typeof(T).Name + "|" + (match == null ? "" : match.ToString()) + "|" + (order == null ? "" : order.ToString()) + "|" + pageIndex + "|" + pageSize;
                    if (cache.Contains(key))
                    {
                        result = (IList<T>)cache.Get(key);
                        rowCount = (int)cache.Get(key + "|count");
                    }
                    else
                    {
                        result = GetCtx(ctxName).GetAll<T>(match, order, out rowCount, (pageIndex - 1) * pageSize, pageSize);
                        cache.Add(key, result, DateTime.Now.AddSeconds(dataCacheTimeout));
                        cache.Add(key + "|count", rowCount, DateTime.Now.AddSeconds(dataCacheTimeout));
                    }
                    result = result.Select(item => (T)item.Clone()).ToList();
                }
                else
                {
                    result = GetCtx(ctxName).GetAll<T>(match, order, out rowCount, (pageIndex - 1) * pageSize, pageSize);
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            count = rowCount;
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="match"></param>
        /// <returns></returns>
        public IList<T> GetAll<T>(Expression<Func<T, bool>> order = null, string ctxName = null, int dataCacheTimeout = 0) where T : BaseModel, IView, new()
        {
            IList<T> result = new List<T>();
            try
            {
                //int dataCacheTimeout = ConfigHelper.GetDataCacheTimeout();
                if (0 != dataCacheTimeout)
                {
                    string key = typeof(T).Name + "||" + (order == null ? "" : order.ToString());
                    if (cache.Contains(key))
                    {
                        result = (IList<T>)cache.Get(key);
                    }
                    else
                    {
                        result = GetCtx(ctxName).GetAll<T>(null, order);
                        cache.Add(key, result, DateTime.Now.AddSeconds(dataCacheTimeout));
                    }
                    result = result.Select(item => (T)item.Clone()).ToList();
                }
                else
                {
                    result = GetCtx(ctxName).GetAll<T>(null, order, 100000);
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="match"></param>
        /// <returns></returns>
        public IList<T> GetAll<T>(int pageIndex, int pageSize, out int count, Expression<Func<T, bool>> order = null, string ctxName = null, int dataCacheTimeout = 0) where T : BaseModel, IView, new()
        {
            IList<T> result = new List<T>();
            int rowCount = 0;
            try
            {
                //int dataCacheTimeout = ConfigHelper.GetDataCacheTimeout();
                if (0 != dataCacheTimeout)
                {
                    string key = typeof(T).Name + "||" + (order == null ? "" : order.ToString()) + "|" + pageIndex + "|" + pageSize;
                    if (cache.Contains(key))
                    {
                        result = (IList<T>)cache.Get(key);
                        rowCount = (int)cache.Get(key + "|count");
                    }
                    else
                    {
                        result = GetCtx(ctxName).GetAll<T>(null, order, out rowCount, (pageIndex - 1) * pageSize, pageSize);
                        cache.Add(key, result, DateTime.Now.AddSeconds(dataCacheTimeout));
                        cache.Add(key + "|count", rowCount, DateTime.Now.AddSeconds(dataCacheTimeout));
                    }
                    result = result.Select(item => (T)item.Clone()).ToList();
                }
                else
                {
                    result = GetCtx(ctxName).GetAll<T>(null, order, out rowCount, (pageIndex - 1) * pageSize, pageSize);
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            count = rowCount;
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public bool ExecuteNonQuery(string sql, string ctxName = null)
        {
            bool result = false;
            try
            {
                if (ConfigHelper.IsShowSQLEnabled())
                {
                    LogOpr.Debug(sql);
                }
                GetCtx(ctxName).ExecuteNonQuery(sql);
                result = true;
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public int ExecuteSqlNonQuery(string sql, string ctxName = null)
        {
            int result = 0;
            try
            {
                if (ConfigHelper.IsShowSQLEnabled())
                {
                    LogOpr.Debug(sql);
                }
                result = GetCtx(ctxName).ExecuteNonQuery(sql);
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public DataTable ExecuteSql(string sql, string ctxName = null, int maxLength = 512, int dataCacheTimeout = 0)
        {
            DataTable result = null;
            try
            {
                if (ConfigHelper.IsShowSQLEnabled())
                {
                    LogOpr.Debug(sql);
                }
                //int dataCacheTimeout = ConfigHelper.GetDataCacheTimeout();
                if (0 != dataCacheTimeout)
                {
                    if (cache.Contains(sql))
                    {
                        result = ((DataTable)cache.Get(sql)).Copy();
                    }
                    else
                    {
                        result = GetCtx(ctxName).ExecuteDataTable(sql, maxLength: maxLength);
                        cache.Add(sql, result.Copy(), DateTime.Now.AddSeconds(dataCacheTimeout));
                    }
                }
                else
                {
                    result = GetCtx(ctxName).ExecuteDataTable(sql, maxLength: maxLength);
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
                result = new DataTable();
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public DataTable ExecuteSql(string sql, int pageIndex, int pageCount, out int count, bool isUnicode = false, string ctxName = null, int dataCacheTimeout = 0, string connectStr = null)
        {
            DataTable result = null;
            count = 0;
            try
            {
                if (ConfigHelper.IsShowSQLEnabled())
                {
                    LogOpr.Debug(sql);
                }

                if (0 != dataCacheTimeout)
                {
                    if (cache.Contains(sql))
                    {
                        result = ((DataTable)cache.Get(sql)).Copy();
                    }
                    else
                    {
                        if (ctxName == null || ctxName == "SysDB")
                        {
                            result = ExecuteSqlByKbaseClient(sql, pageIndex, pageCount, isUnicode, out count, connectStr);
                        }
                        else if (ctxName == "mysql")
                        {
                            result = ExecuteSqlByMySQLClient1(sql, pageIndex, pageCount, out count, connectStr);
                        }
                        if (result != null)
                        {
                            cache.Add(sql, result.Copy(), DateTime.Now.AddSeconds(dataCacheTimeout));
                        }
                    }
                }
                else
                {
                    if (ctxName == null || ctxName == "SysDB")
                    {
                        result = ExecuteSqlByKbaseClient(sql, pageIndex, pageCount, isUnicode, out count, connectStr);
                    }
                    else if (ctxName == "mysql")
                    {
                        //Stopwatch sw = new Stopwatch();
                        //sw.Start();
                        //result = ExecuteSqlByMySQLClient(sql, pageIndex, pageCount, out count, connectStr);
                        //sw.Stop();
                        //LogOpr.Error("Execute ExecuteSqlByMySQLClient = "+ sw.ElapsedMilliseconds);
                        //sw.Reset();
                        //sw.Start();
                        result = ExecuteSqlByMySQLClient1(sql, pageIndex, pageCount, out count, connectStr);
                        //sw.Stop();
                        //LogOpr.Error("Execute ExecuteSqlByMySQLClient1 = " + sw.ElapsedMilliseconds);
                    }
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
                result = new DataTable();
            }
            return result;
        }

        private DataTable ExecuteSqlByKbaseClient(string sql, int pageIndex, int pageCount, bool isUnicode, out int count, string connectStr = null)
        {
            DataTable result = null;
            string connectionString = "";
            if (string.IsNullOrEmpty(connectStr))
            {
                connectionString = ConfigHelper.GetConnSettingsValue("SysDB");
                connectionString = connectionString.Substring(connectionString.IndexOf(':') + 1);
            }
            else
            {
                connectionString = connectStr;
            }

            count = 0;
            using (KBaseConnection connection = new KBaseConnection(connectionString))
            {
                KBaseCommand command = new KBaseCommand(sql, connection);
                command.IsUnicode = isUnicode;
                //dr.IsHighlighted = true;
                connection.Open();
                KBaseDataReader dr = command.ExecuteReader();
                count = dr.Count;
                if (count > 0)
                {
                    DataTable dt = new DataTable();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        dt.Columns.Add(dr.GetName(i));
                    }
                    for (int i = pageCount * (pageIndex - 1) + 1; i <= pageCount * pageIndex; i++)
                    {
                        if (dr.Move(i))
                        {
                            DataRow dataRow = dt.NewRow();
                            for (int j = 0; j < dr.FieldCount; j++)
                            {
                                dataRow[j] = dr.GetValue(j);
                            }
                            dt.Rows.Add(dataRow);
                        }
                        else
                        {
                            break;
                        }
                    }
                    result = dt;
                }
                connection.Close();
            }
            return result;
        }

        private DataTable ExecuteSqlByMySQLClient(string sql, int pageIndex, int pageCount, out int count, string connectStr = null)
        {
            DataTable result = null;
            count = 0;
            string connectionString = "";
            if (string.IsNullOrEmpty(connectStr))
            {
                connectionString = ConfigHelper.GetConnSettingsValue("mysql");
                connectionString = connectionString.Substring(connectionString.IndexOf(':') + 1);
            }
            else
            {
                connectionString = connectStr;
            }

            using (MySqlConnection connection = new MySqlConnection(connectionString))
            {
                MySqlCommand command = new MySqlCommand(sql, connection);
                //dr.IsHighlighted = true;
                connection.Open();
                MySqlDataReader dr = command.ExecuteReader();
                count = 0;
                DataTable dt = new DataTable();
                for (int i = 0; i < dr.FieldCount; i++)
                {
                    dt.Columns.Add(dr.GetName(i));
                }
                int index = -1;
                while (dr.Read())
                {
                    count++;
                    index++;
                    if (index >= pageCount * (pageIndex - 1) && index < pageCount * pageIndex)
                    {
                        DataRow dataRow = dt.NewRow();
                        for (int j = 0; j < dr.FieldCount; j++)
                        {
                            dataRow[j] = dr.GetValue(j);
                        }
                        dt.Rows.Add(dataRow);
                    }
                    result = dt;
                }
                connection.Close();
            }
            return result;
        }
        private DataTable ExecuteSqlByMySQLClient1(string sql, int pageIndex, int pageCount, out int count, string connectStr = null)
        {
            DataTable result = null;
            count = 0;
            try {
                result = ExecuteSql(string.Format("{0} limit {1},{2}", sql, (pageIndex-1)*pageCount, pageCount), "mysql");
                string countSql = Regex.Replace(sql, @"(?<=^select)[\s\S]*?(?=from)", " count(1) ", RegexOptions.IgnoreCase);
                DataTable countInfo = ExecuteSql(countSql, "mysql");
                if (countInfo != null && countInfo.Rows.Count > 0)
                {
                    count = int.Parse(countInfo.Rows[0][0].ToString());
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }
        private DataTable ExecuteSqlByMySQLClient2(string sql, int pageIndex, int pageCount, out int count, string connectStr = null)
        {
            DataTable result = null;
            count = 0;
            string connectionString = "";
            if (string.IsNullOrEmpty(connectStr))
            {
                connectionString = ConfigHelper.GetConnSettingsValue("mysql");
                connectionString = connectionString.Substring(connectionString.IndexOf(':') + 1);
            }
            else
            {
                connectionString = connectStr;
            }

            using (MySqlConnection connection = new MySqlConnection(connectionString))
            {
                MySqlCommand command = new MySqlCommand(sql, connection);
                //dr.IsHighlighted = true;
                connection.Open();
                MySqlDataReader dr = command.ExecuteReader();
                MySqlDataAdapter da = new MySqlDataAdapter();
                count = 0;
                DataTable dt = new DataTable();
                for (int i = 0; i < dr.FieldCount; i++)
                {
                    dt.Columns.Add(dr.GetName(i));
                }
                int index = -1;
                while (dr.Read())
                {
                    count++;
                    index++;
                    if (index >= pageCount * (pageIndex - 1) && index < pageCount * pageIndex)
                    {
                        DataRow dataRow = dt.NewRow();
                        for (int j = 0; j < dr.FieldCount; j++)
                        {
                            dataRow[j] = dr.GetValue(j);
                        }
                        dt.Rows.Add(dataRow);
                    }
                    result = dt;
                }
                connection.Close();
            }
            return result;
        }
        public DataSet ExecuteSql(string sql, IList<string> tableList, int pageIndex, int pageCount, bool isUnicode = false, string ctxName = null, int dataCacheTimeout = 0)
        {
            DataSet result = null;
            try
            {
                if (ConfigHelper.IsShowSQLEnabled())
                {
                    LogOpr.Debug(sql);
                }

                if (0 != dataCacheTimeout)
                {
                    string limit = pageCount * (pageIndex - 1) + "," + pageCount;
                    string key = sql + " limit " + limit;
                    if (cache.Contains(key))
                    {
                        result = ((DataSet)cache.Get(key)).Copy();
                    }
                    else
                    {
                        result = ExecuteSqlByKbaseClient(sql, tableList, pageIndex, pageCount, isUnicode);
                        if (result != null)
                        {
                            cache.Add(key, result.Copy(), DateTime.Now.AddSeconds(dataCacheTimeout));
                        }
                    }
                }
                else
                {
                    result = ExecuteSqlByKbaseClient(sql, tableList, pageIndex, pageCount, isUnicode);
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
                result = new DataSet();
            }
            return result;
        }

        private DataSet ExecuteSqlByKbaseClient(string sql, IList<string> tableList, int pageIndex, int pageCount, bool isUnicode)
        {
            DataSet result = new DataSet();
            DataTable data = new DataTable();
            DataTable tableInfo = new DataTable("infos");
            tableInfo.Columns.Add("name");
            tableInfo.Columns.Add("count", typeof(Int32));

            string connectionString = ConfigHelper.GetConnSettingsValue("SysDB");
            connectionString = connectionString.Substring(connectionString.IndexOf(':') + 1);
            using (KBaseConnection connection = new KBaseConnection(connectionString))
            {
                KBaseCommand command = new KBaseCommand(sql, connection);
                command.IsUnicode = isUnicode;
                connection.Open();
                KBaseDataReader dr = command.ExecuteReader();
                dr.Prefix = "###";//默认是"###"
                dr.Postfix = "$$$";//默认是"$$$"
                dr.IsHighlighted = true;
                int count = dr.Count;
                if (count > 0)
                {
                    DataTable dt = new DataTable();
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        dt.Columns.Add(dr.GetName(i));
                    }
                    for (int i = pageCount * (pageIndex - 1) + 1; i <= pageCount * pageIndex; i++)
                    {
                        if (dr.Move(i))
                        {
                            DataRow dataRow = dt.NewRow();
                            for (int j = 0; j < dr.FieldCount; j++)
                            {
                                dataRow[j] = dr.GetValue(j);
                            }
                            dt.Rows.Add(dataRow);
                        }
                        else
                        {
                            break;
                        }
                    }
                    data = dt;

                    DataRow row = tableInfo.NewRow();
                    foreach (string tableName in tableList)
                    {
                        row = tableInfo.NewRow();
                        row[0] = tableName;
                        row[1] = dr.GetVQRecordCountByName(tableName);
                        tableInfo.Rows.Add(row);
                    }
                }
                connection.Close();
                result.Tables.Add(data);
                result.Tables.Add(tableInfo);
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <returns></returns>
        public IList<T> ExecuteSql<T>(string sql, string ctxName = null, int maxLength = -1, int dataCacheTimeout = 0) where T : BaseModel, IView, new()
        {
            IList<T> result = null;
            try
            {
                if (ConfigHelper.IsShowSQLEnabled())
                {
                    LogOpr.Debug(sql);
                }

                //int dataCacheTimeout = ConfigHelper.GetDataCacheTimeout();
                if (0 != dataCacheTimeout)
                {
                    string key = sql + "|" + maxLength;
                    if (cache.Contains(key))
                    {
                        result = (IList<T>)cache.Get(key);
                    }
                    else
                    {
                        if (-1 == maxLength)
                        {
                            result = GetCtx(ctxName).Execute<T>(sql);
                        }
                        else
                        {
                            result = GetCtx(ctxName).Execute<T>(sql, null, maxLength);
                        }
                        cache.Add(key, result, DateTime.Now.AddMinutes(dataCacheTimeout));
                    }
                    result = result.Select(item => (T)item.Clone()).ToList();
                }
                else
                {
                    if (-1 == maxLength)
                    {
                        result = GetCtx(ctxName).Execute<T>(sql);
                    }
                    else
                    {
                        result = GetCtx(ctxName).Execute<T>(sql, null, maxLength);
                    }
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="fields"></param>
        /// <param name="query"></param>
        /// <param name="group"></param>
        /// <param name="order"></param>
        /// <param name="start"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public DataSet QueryByDRS(string type, string fields, string query, string group, string order, int start, int length)
        {
            DataSet result = new DataSet();
            IRetrievalService drs = null;
            try
            {
                drs = channel.CreateChannel();
                result = drs.GetAll(type, fields, query, group, order, start, length).DataSet;
                ((ICommunicationObject)drs).Close();
            }
            catch (CommunicationException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (TimeoutException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (Exception)
            {
                ((ICommunicationObject)drs).Abort();
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="drsName"></param>
        /// <param name="resource"></param>
        /// <returns></returns>
        public OperateResult AppendDbResource(string drsName, DbResource resource, decimal weight, string group)
        {
            OperateResult result = null;
            IRetrievalService drs = null;
            try
            {
                drs = channel.CreateChannel();
                result = drs.AppendDbResourceByArg(drsName, resource, weight, group);
                ((ICommunicationObject)drs).Close();
            }
            catch (CommunicationException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (TimeoutException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (Exception)
            {
                ((ICommunicationObject)drs).Abort();
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="retrieval"></param>
        /// <returns></returns>
        public OperateResult AppendRetrieval(Retrieval retrieval)
        {
            OperateResult result = null;
            IRetrievalService drs = null;
            try
            {
                drs = channel.CreateChannel();
                result = drs.AppendRetrieval(retrieval);
                ((ICommunicationObject)drs).Close();
            }
            catch (CommunicationException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (TimeoutException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (Exception)
            {
                ((ICommunicationObject)drs).Abort();
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="drsName"></param>
        /// <param name="resourceName"></param>
        /// <returns></returns>
        public OperateResult RemoveResource(string drsName, string resourceName)
        {
            OperateResult result = null;
            IRetrievalService drs = null;
            try
            {
                drs = channel.CreateChannel();
                result = drs.RemoveResource(drsName, resourceName);
                ((ICommunicationObject)drs).Close();
            }
            catch (CommunicationException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (TimeoutException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (Exception)
            {
                ((ICommunicationObject)drs).Abort();
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="drsName"></param>
        /// <returns></returns>
        public OperateResult RemoveRetrieval(string drsName)
        {
            OperateResult result = null;
            IRetrievalService drs = null;
            try
            {
                drs = channel.CreateChannel();
                result = drs.RemoveRetrieval(drsName);
                ((ICommunicationObject)drs).Close();
            }
            catch (CommunicationException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (TimeoutException)
            {
                ((ICommunicationObject)drs).Abort();
            }
            catch (Exception)
            {
                ((ICommunicationObject)drs).Abort();
            }
            return result;
        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="match"></param>
        /// <returns></returns>
        public IList<T> Gets<T>(Expression<Func<T, bool>> match, int start, int length, out int count, Expression<Func<T, bool>> order = null,
            bool loadLazy = false, string tableName = null, string ctxName = null) where T : IView, new()
        {
            IList<T> result = new List<T>();
            count = 0;
            try
            {
                result = GetCtx(ctxName).GetAll(match, start, length, out count, order, loadLazy, tableName);
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        public int InsertRec(string tableName, string content, bool isUnicode)
        {
            int result = 0;
            string connstr = ConfigHelper.GetConnSettingsValue("SysDB");
            connstr = connstr.Substring(connstr.IndexOf(':') + 1);
            KBaseConnection conn = new KBaseConnection(connstr);
            try
            {
                conn.Open();
                KBase_ADD_RECORD addRec = new KBase_ADD_RECORD();
                addRec.RecordBuf = content;
                addRec.DataLen = content.Length;
                addRec.TableName = tableName;
                result = TPIClient.KBase_AddRecData(conn.HCon, ref addRec, content.Length, content, isUnicode);
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            finally
            {
                conn.Close();
            }
            return result;
        }


        public bool UpdateRec(string sysid, string tableName, string content, bool isUnicode)
        {
            bool result = false;
            string connstr = ConfigHelper.GetConnSettingsValue("SysDB");
            string fileName = tableName + "_" + sysid + ".txt";
            string srcFile = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + fileName;
            string targetFile = "";
            connstr = connstr.Substring(connstr.IndexOf(':') + 1);
            string sql = "DBUM UPDATE TABLE {0} FROM '{1}' WITH KEY SYS_FLD_SYSID";
            KBaseConnection conn = new KBaseConnection(connstr);
            try
            {
                conn.Open();
                //获得服务器路径
                StringBuilder path = new StringBuilder(512);
                int nRet = TPIClient.KBase_GetServerPath(conn.HCon, path);
                if (nRet < 0)
                {
                    LogOpr.Error("获取服务器路径失败");
                    return result;
                }
                else
                {
                    targetFile = path.ToString() + "\\" + fileName;
                }
                //生成文件
                CreateRecFile(content, isUnicode, srcFile);
                //上传文件
                nRet = TPIClient.KBase_WriteFile(conn.HCon, srcFile, targetFile);
                if (nRet < 0)
                {
                    LogOpr.Error("上传REC文件失败");
                    return result;
                }
                //更新数据
                result = ExecuteNonQuery(string.Format(sql, tableName, targetFile));
                //删除临时文件
                File.Delete(srcFile);
                nRet = TPIClient.KBase_DeleteFiles(conn.HCon, new StringBuilder(targetFile));
                if (nRet < 0)
                {
                    LogOpr.Error("删除REC文件失败");
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            finally
            {
                conn.Close();
            }
            return result;
        }

        private static bool CreateRecFile(string content, bool isUnicode, string srcFile)
        {
            bool result = false;
            try
            {
                StreamWriter sw = null;
                if (isUnicode)
                {
                    sw = new StreamWriter(srcFile, false, Encoding.UTF8);
                }
                else
                {
                    sw = new StreamWriter(srcFile, false, Encoding.Default);
                }
                sw.Write(content);
                sw.Flush();
                sw.Close();
                result = true;
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        public HS_TABLE_FIELD GetFieldInfo(string tableName, string fieldName)
        {
            HS_TABLE_FIELD result = new HS_TABLE_FIELD();
            string connstr = ConfigHelper.GetConnSettingsValue("SysDB");
            connstr = connstr.Substring(connstr.IndexOf(':') + 1);
            KBaseConnection conn = new KBaseConnection(connstr);
            try
            {
                conn.Open();
                IntPtr pInfo;
                int size = Marshal.SizeOf(typeof(KBase_TABLE_INFO));
                pInfo = Marshal.AllocHGlobal(size);
                TPIClient.KBase_GetTableInfoFromCache(conn.HCon, tableName, pInfo, ref size);
                KBase_TABLE_INFO srcTableInfo = (KBase_TABLE_INFO)Marshal.PtrToStructure(pInfo, typeof(KBase_TABLE_INFO));
                for (int i = 0; i < srcTableInfo.TableHead.FieldNum; i++)
                {
                    if (srcTableInfo.TableField[i].Name.ToUpper().Equals(fieldName.ToUpper()))
                    {
                        result = srcTableInfo.TableField[i];
                        break;
                    }
                }
                Marshal.FreeHGlobal(pInfo);
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            finally
            {
                conn.Close();
            }
            return result;
        }

        public byte[] GetBinary(string id)
        {
            byte[] buf = null;
            string connstr = ConfigHelper.GetConnSettingsValue("SysDB");
            connstr = connstr.Substring(connstr.IndexOf(':') + 1);
            KBaseConnection conn = new KBaseConnection(connstr);
            try
            {
                conn.Open();
                string ksql = "select DATA, length from BINARYDATAVIEW where urlid= " + id;
                int nRet = 0;
                TPI_HRECORDSET hSet = TPIClient.KBase_OpenRecordSet(conn.HCon, ksql, ref nRet);
                int col = 0; // 表示修改第一列
                int rec = 0; // 表示修改第一个记录
                int offset = 0;



                int nBufLen = 256;
                StringBuilder value = new StringBuilder(nBufLen);
                nRet = TPIClient.KBase_GetFieldValue(hSet, 1, value, nBufLen);
                if (nRet > 0)
                {
                    if (!string.IsNullOrEmpty(value.ToString()))
                    {
                        int length = int.Parse(value.ToString());
                        if (length > 0)
                        {
                            buf = new byte[length + 1];
                            nRet = TPIClient.KBase_GetBLob(hSet, col, rec, offset, buf, length);
                            if (nRet == 0)
                            {
                                return null;
                            }
                        }
                    }
                }



                TPIClient.KBase_CloseRecordSet(hSet);
                TPIClient.KBase_CloseCon(conn.HCon);
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            finally
            {
                conn.Close();
            }
            return buf;
        }

        public bool SaveFile(string srcFile, string targetFile)
        {
            bool result = false;
            string connstr = ConfigHelper.GetConnSettingsValue("SysDB");
            connstr = connstr.Substring(connstr.IndexOf(':') + 1);
            KBaseConnection conn = new KBaseConnection(connstr);
            try
            {
                conn.Open();
                //检查目录是否存在
                string filePath = targetFile.Substring(0, targetFile.LastIndexOf(Path.DirectorySeparatorChar));
                int nRet = TPIClient.KBase_FileExists(conn.HCon, filePath);
                if (nRet == 0)
                {
                    nRet = TPIClient.KBase_MakeDir(conn.HCon, filePath);
                    if (nRet < 0)
                    {
                        LogOpr.Error("创建目录失败 " + filePath);
                        return result;
                    }
                }
                //上传文件
                nRet = TPIClient.KBase_WriteFile(conn.HCon, srcFile, targetFile);
                if (nRet < 0)
                {
                    LogOpr.Error("上传REC文件失败");
                    return result;
                }
                else
                {
                    result = true;
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            finally
            {
                conn.Close();
            }
            return result;
        }

        public bool DeleteFile(string filePath)
        {
            bool result = false;
            string connstr = ConfigHelper.GetConnSettingsValue("SysDB");
            connstr = connstr.Substring(connstr.IndexOf(':') + 1);
            KBaseConnection conn = new KBaseConnection(connstr);
            try
            {
                conn.Open();
                //上传文件
                int nRet = TPIClient.KBase_FileExists(conn.HCon, filePath);
                if (nRet == 1)
                {
                    nRet = TPIClient.KBase_DeleteFiles(conn.HCon, new StringBuilder(filePath));
                    if (nRet < 0)
                    {
                        LogOpr.Error("上传REC文件失败");
                        return result;
                    }
                    else
                    {
                        result = true;
                    }
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            finally
            {
                conn.Close();
            }
            return result;
        }
    }
}
